package com.jwcao.common.scan.object;

import com.esotericsoftware.reflectasm.FieldAccess;
import com.esotericsoftware.reflectasm.MethodAccess;
import com.jwcao.common.utils.ReflectUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import lombok.Getter;
import lombok.Setter;

/**
 * name: ScanField description: TODO
 *
 * @author caojingwei date: 2023/3/22 10:31
 */
@Getter
@Setter
public class ScanField<T> {

    private final String name;
    private final Field field;
    private final Class<T> parentClass;
    private final FieldAccess fieldAccess;
    private final MethodAccess methodAccess;
    private final FieldAccessMethod getterMethod;
    private final FieldAccessMethod setterMethod;


    private final int getterIndex;
    private final int setterIndex;

    public boolean isAbstractOrInterface() {
        return ReflectUtil.isAbstractOrInterface(field.getType());
    }

    public boolean equalType(ScanField scanField) {
        return field.getType() == scanField.getField().getType();
    }

    public Class<?> getFieldType() {
        return field.getType();
    }

    public ScanField(Field field, Class<T> parentClass, FieldAccess fieldAccess, MethodAccess methodAccess) {
        this.name = field.getName();
        this.field = field;
        this.parentClass = parentClass;
        this.fieldAccess = fieldAccess;
        this.methodAccess = methodAccess;
        getterMethod = FieldAccessMethod.judgeGetter(field, methodAccess);
        setterMethod = FieldAccessMethod.judgeSetter(field, methodAccess);
        getterIndex = getterMethod.getterIndex(this);
        setterIndex = setterMethod.setterIndex(this);
    }

    public Object get(Object target) {
        return getterMethod.get(this, target);
    }

    public void set(Object target, Object value) {
        setterMethod.set(this, target, value);
    }
}
